from django.test import TestCase
from django.core.files.uploadedfile import SimpleUploadedFile
from django.urls import reverse
from rest_framework import status
from rest_framework.test import APITestCase, APIClient
from django.contrib.auth import get_user_model
from .models import Document
import os
import shutil
from django.conf import settings

# Create your tests here.

class DocumentModelTest(TestCase):
    def setUp(self):
        # 创建测试文件
        self.test_file = SimpleUploadedFile(
            "test_file.txt",
            b"Test file content",
            content_type="text/plain"
        )
        
        # 创建测试文档
        self.document = Document.objects.create(
            title="Test Document",
            file=self.test_file,
            file_size=len(b"Test file content"),
            upload_ip="127.0.0.1"
        )
    
    def tearDown(self):
        # 清理测试文件
        try:
            if self.document.file:
                file_path = self.document.file.path
                if os.path.isfile(file_path):
                    os.close(os.open(file_path, os.O_RDONLY))  # 确保文件句柄已关闭
                    os.remove(file_path)
        except Exception as e:
            print(f"清理文件时出错: {e}")
    
    def test_document_creation(self):
        """测试文档创建"""
        self.assertEqual(self.document.title, "Test Document")
        self.assertEqual(self.document.file_type, "TXT")
        self.assertEqual(self.document.file_size, len(b"Test file content"))
        self.assertEqual(self.document.download_count, 0)
    
    def test_document_str(self):
        """测试文档字符串表示"""
        self.assertEqual(str(self.document), "Test Document")

class DocumentAPITest(APITestCase):
    def setUp(self):
        # 创建测试用户
        User = get_user_model()
        self.user = User.objects.create_user(
            username='testuser',
            password='testpass123'
        )
        
        # 创建测试文件
        self.test_file = SimpleUploadedFile(
            "test_file.txt",
            b"Test file content",
            content_type="text/plain"
        )
        
        # 创建测试文档
        self.document = Document.objects.create(
            title="Test Document",
            file=self.test_file,
            file_size=len(b"Test file content"),
            upload_ip="127.0.0.1"
        )
        
        # 设置API客户端
        self.client = APIClient()
    
    def tearDown(self):
        # 清理测试文件
        try:
            if hasattr(self, 'document') and self.document.file:
                file_path = self.document.file.path
                if os.path.isfile(file_path):
                    os.close(os.open(file_path, os.O_RDONLY))  # 确保文件句柄已关闭
                    os.remove(file_path)
            
            # 清理测试媒体目录
            media_test_dir = os.path.join(settings.MEDIA_ROOT, 'documents')
            if os.path.exists(media_test_dir):
                shutil.rmtree(media_test_dir, ignore_errors=True)
        except Exception as e:
            print(f"清理文件时出错: {e}")
    
    def test_document_list(self):
        """测试获取文档列表"""
        url = reverse('document-list')
        response = self.client.get(url)
        self.assertEqual(response.status_code, status.HTTP_200_OK)
        self.assertEqual(len(response.data), 1)
    
    def test_document_detail(self):
        """测试获取文档详情"""
        url = reverse('document-detail', args=[self.document.id])
        response = self.client.get(url)
        self.assertEqual(response.status_code, status.HTTP_200_OK)
        self.assertEqual(response.data['title'], "Test Document")
    
    def test_document_download(self):
        """测试文档下载"""
        url = reverse('document-download', args=[self.document.id])
        response = self.client.get(url)
        self.assertEqual(response.status_code, status.HTTP_200_OK)
        
        # 验证下载计数增加
        self.document.refresh_from_db()
        self.assertEqual(self.document.download_count, 1)
    
    def test_document_create_authenticated(self):
        """测试认证用户创建文档"""
        self.client.force_authenticate(user=self.user)
        url = reverse('document-list')
        test_file = SimpleUploadedFile(
            "new_test.txt",
            b"New test content",
            content_type="text/plain"
        )
        response = self.client.post(url, {
            'title': 'New Document',
            'file': test_file
        }, format='multipart')
        self.assertEqual(response.status_code, status.HTTP_201_CREATED)
        self.assertEqual(Document.objects.count(), 2)
    
    def test_document_create_unauthenticated(self):
        """测试未认证用户创建文档"""
        url = reverse('document-list')
        test_file = SimpleUploadedFile(
            "new_test.txt",
            b"New test content",
            content_type="text/plain"
        )
        response = self.client.post(url, {
            'title': 'New Document',
            'file': test_file
        }, format='multipart')
        self.assertEqual(response.status_code, status.HTTP_401_UNAUTHORIZED)
        self.assertEqual(Document.objects.count(), 1)
